﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

namespace WindowsGame1
{
    
    
    public class PrototypeEnemy: CollidableObject
    {
        const int MOVE_UP = -1;
        const int MOVE_DOWN = 1;
        const int MOVE_LEFT = -1;
        const int MOVE_RIGHT = 1;

        //Default values for running enemy. Stored here so we do not have to hunt all instances down if we change it
        protected const int DEFAULTHP = 5;
        protected const int DEFAULTDMG = 1;
        protected const int DEFAULTSPEED = 200;
        protected const double DEFAULTATTACKTIME = 1000;
        protected const double DEFAULTATTACKDELAY = 500;
        protected const int DEFAULTRANGE = 50;

        //Graphic Information
        public string AssetName = "SquareGoblin";
        public string AttackAssetName = "squareGoblinAttack";

        //This Enemy's Stats
        protected int maxSpeed;
        protected int hp;
        protected int damage;
        protected double attackTime;
        protected double attackDelay;
        protected double attackRange;

        //How far away the enemy will attempt t0 flee to
        protected int cowardace = 0;

        //Enemy that this enemy spawns
        protected Boolean spawnsChildren;
        protected int childMaxSpeed;
        protected int childhp;
        protected int childDamage;
        protected double childAttackTime;
        protected double childAttackDelay;
        protected double childAttackRange;

        protected enum State
        {
            Walking,
            Attacking,
            Paused
        }
        protected State CurrentState = State.Walking;

        //Which of the four characters the Enemy wants to kill
        public CollidableObject currentTarget;

        //Movement/direction direction varaibles
        Vector2 mDirection = Vector2.Zero;
        Vector2 mSpeed = Vector2.Zero;

        //Hitbox varaibles
        public Rectangle HitBox;
        private float mScale = 1.0f;

        //Texture variables
        public Texture2D mSpriteTexture;
        public Texture2D mAttackSpriteTexture;
        public Texture2D currentTexture;

        //Time of last attack
        protected double lastAttack = 0;

        //Time attack started
        protected double attackStart = 0;

        //Things to Create
        protected List<CollidableObject> makeList = new List<CollidableObject>();

        public PrototypeEnemy()
        {
            maxSpeed = DEFAULTSPEED;
            hp = DEFAULTHP;
            damage = DEFAULTDMG;
            attackTime = DEFAULTATTACKTIME;
            attackDelay = DEFAULTATTACKDELAY;
            attackRange = DEFAULTRANGE;
            Position = new Vector2(100, 100);
            spawnsChildren = false;
        }


        //Load the texture for the sprite using the Content Pipeline
        internal override void LoadContent(ContentManager theContentManager)
        {
            mSpriteTexture = theContentManager.Load<Texture2D>(AssetName);
            mAttackSpriteTexture = theContentManager.Load<Texture2D>(AttackAssetName);
            currentTexture = mSpriteTexture;
            HitBox = new Rectangle(0, 0, (int)(mSpriteTexture.Width * mScale), (int)(mSpriteTexture.Height * mScale));
        }

        internal override void Update(GameTime theGameTime)
        {
            if (CurrentState == State.Walking)
            {
                movement(theGameTime);
                AttackCheck(theGameTime);
            }
            else if ((CurrentState == State.Attacking) || (CurrentState == State.Paused))
            {
                attackCoolDown(theGameTime);
            }
        }

        internal override void Draw(GameTime gameTime, SpriteBatch spriteBatch)
        {
            // TODO: Add your drawing code here
            spriteBatch.Draw(currentTexture, Position, Color.White);
        }

        private void UpdateMovementToTarget(GameTime gameTime)
        {
            if (Vector2.Distance(Position, currentTarget.Position) > 50)
            {
                mDirection = (currentTarget.Position - Position);
                mDirection.Normalize();

                mSpeed = new Vector2 (Math.Abs(mDirection.X) * maxSpeed, Math.Abs(mDirection.Y) * maxSpeed);
            }
            else
            {
                mDirection = Vector2.Zero;
                mSpeed = Vector2.Zero;
            }
        }

        internal void GetDunked(PrototypeProjectile protojectile)
        {
            Vector2 mTrajectory = new Vector2(protojectile.GetHitBox().Center.X + .01f - HitBox.Center.X, protojectile.GetHitBox().Center.Y + .01f - HitBox.Center.Y);
            mTrajectory.Normalize();
            Position += mTrajectory * 200;
        }


        protected void ATTACKTHEMHEADON(GameTime theGameTime)
        {
            HitBox.Location = new Point((int)Position.X, (int)Position.Y);
            UpdateMovementToTarget(theGameTime);


            Position += mDirection * mSpeed * (float)theGameTime.ElapsedGameTime.TotalSeconds;
        }

        protected void likeABitch(GameTime theGameTime)
        {
            if (Vector2.Distance(Position, currentTarget.Position) < cowardace)
            {
                HitBox.Location = new Point((int)Position.X, (int)Position.Y);
                UpdateMovementToTarget(theGameTime);


                Position -= mDirection * mSpeed * (float)theGameTime.ElapsedGameTime.TotalSeconds;
            }
        }

        public List<CollidableObject> getMakeList()
        {
            return makeList;
        }

        protected void addMakeList(CollidableObject obj)
        {
            makeList.Add(obj);
        }

        public void clearMakeList()
        {
            makeList.Clear();
        }


        //Life Cycle:
        //Movement()/AttackCheck()
        //transitionToAttacking()
        //performAttack()
        //TransisitionToWaiting()
        //CoolDown()
        //TransitionToMoving()
        internal virtual void movement(GameTime theGameTime)
        {
            ATTACKTHEMHEADON(theGameTime);
        }

        //Checks if in Range to attack and if it has been long enouch since last attack
        //If both checks pass moves to Attacking State
        internal void AttackCheck(GameTime theGameTime)
        {
            if (Vector2.Distance(Position, currentTarget.Position) <= attackRange)
            {
                if ((theGameTime.TotalGameTime.TotalMilliseconds - lastAttack) > attackTime)
                {
                    CurrentState = State.Attacking;
                    transitionToAttacking();
                    attackStart = theGameTime.TotalGameTime.TotalMilliseconds;
                }
            }

        }

        internal virtual void transitionToAttacking()
        {

        }

        internal virtual void performAttack()
        {

        }

        internal virtual void transitionToWaiting()
        {

        }

        public void attackCoolDown(GameTime theGameTime)
        {
            if (CurrentState == State.Attacking)
            {
                if ((theGameTime.TotalGameTime.TotalMilliseconds - attackStart) > attackDelay)
                {
                    performAttack();
                    lastAttack = theGameTime.TotalGameTime.TotalMilliseconds;
                    CurrentState = State.Paused;
                    transitionToWaiting();
                }
            }
            else if (CurrentState == State.Paused)
            {
                if ((theGameTime.TotalGameTime.TotalMilliseconds - lastAttack) > attackDelay){
                    CurrentState = State.Walking;
                    transitionToWalking();
                }
            }
        }

        internal virtual void transitionToWalking()
        {

        }
    }
}
